package com.smart.manager.system.repository;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.StrUtil;
import com.smart.common.entities.constant.ArcoTips;
import com.smart.common.entities.core.Page;
import com.smart.common.entities.option.SelectOption;
import com.smart.common.entities.option.SelectOptionMap;
import com.smart.manager.system.entities.body.RSystemDict;
import com.smart.manager.system.entities.enums.DictRwState;
import com.smart.manager.system.entities.models.SystemDict;
import com.smart.manager.system.entities.models.query.QSystemDict;
import io.ebean.DB;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Log4j2
public class DictRepository {


    public Page<SystemDict> pageList(RSystemDict.SearchBody search) {
        QSystemDict query = new QSystemDict();
        Opt.ofBlankAble(search.getCode()).ifPresent(x -> query.code.contains(x));
        Opt.ofBlankAble(search.getName()).ifPresent(x -> query.title.contains(x));
        Opt.ofNullable(search.getState()).ifPresent(x -> query.state.eq(x));
        Opt.ofNullable(search.getRwState()).ifPresent(x -> query.rwState.eq(x));
        query.order().id.desc();
        query.setFirstRow(search.firstRow()).setMaxRows(search.maxRows());
        return new Page<SystemDict>().load(query.findPagedList());
    }

    public void add(RSystemDict.EditBody body) {
        QSystemDict query = new QSystemDict();
        SystemDict record = query.code.eq(body.getCode()).setMaxRows(1).findOne();
        Assert.isNull(record, "创建失败:, 模块代码已存在");
        BeanUtil.copyProperties(body, SystemDict.class)
                .setRwState(DictRwState.FULL)
                .save();
    }


    public void update(Long id, RSystemDict.EditBody body) {
        SystemDict record = new QSystemDict().id.eq(id).setMaxRows(1).findOne();
        Assert.notNull(record, ArcoTips.UPDATE_NOT_FOUND);
        BeanUtil.copyProperties(body, record);
        record.setRwState(DictRwState.FULL);
        Objects.requireNonNull(record).update();

    }

    public int delByIds(List<Long> ids) {
        List<SystemDict> list = new QSystemDict().id.in(ids).findList();
        Assert.notEmpty(list, ArcoTips.DELETE_NOT_FOUND);
        for (SystemDict module : list) {
            log.warn("检查数据是否允许被删除  {}", module);
        }
        return DB.deleteAll(list);


    }


    /**
     * 对比更新所有枚举字典
     *
     * @param currentAllEnumDict 当前所有枚举dict类型
     */
    @Transactional(rollbackFor = Exception.class)
    public void contrastUpdate(List<SystemDict> currentAllEnumDict) {
        List<SystemDict> dictList = new QSystemDict().rwState.eq(DictRwState.READ).findList();
        //  新数据 老数据都是看哪个的 直接退出
        if (CollUtil.isEmpty(currentAllEnumDict) && CollUtil.isEmpty(dictList)) {
            return;
        }


        // 没有最新数据 直接删除历史数据
        if (CollUtil.isEmpty(currentAllEnumDict) && CollUtil.isNotEmpty(dictList)) {
            List<Long> idList = dictList.stream().map(SystemDict::getId).collect(Collectors.toList());
            DB.deleteAll(SystemDict.class, idList);
            return;
        }

        // 没有历史数据 只有新数据 直接全量新增新数据
        if (CollUtil.isEmpty(dictList) && CollUtil.isNotEmpty(currentAllEnumDict)) {
            DB.insertAll(currentAllEnumDict);
            return;
        }
        ArrayList<SystemDict> addLists = new ArrayList<>();
        ArrayList<SystemDict> updateList = new ArrayList<>();
        ArrayList<SystemDict> deleteList = new ArrayList<>();
        assert currentAllEnumDict != null;
        List<String> newCodes = currentAllEnumDict.stream().map(SystemDict::getCode).collect(Collectors.toList());
        List<String> oldCodes = dictList.stream().map(SystemDict::getCode).collect(Collectors.toList());
        currentAllEnumDict.forEach(item -> {

            if (oldCodes.contains(item.getCode())) {
                Optional<SystemDict> first = dictList.stream().filter(x -> x.getCode().equals(item.getCode())).findFirst();
                //没有匹配数据 跳出
                if (first.isEmpty()) {
                    return;
                }
                SystemDict dict = first.get();
                //标题或字典明细发生改变时 刷新信息
                if (!StrUtil.equals(dict.getTitle(), item.getTitle()) || !StrUtil.equals(item.getItems().toString(), dict.getItems().toString())) {
                    //忽略ID 和乐观锁标志
                    BeanUtil.copyProperties(item, dict, "id", "version");
                    updateList.add(dict);
                }


            } else {
                addLists.add(item);
            }
        });
        dictList.forEach(item -> {
            if (!newCodes.contains(item.getCode())) {
                deleteList.add(item);
            }
        });
        if (addLists.size() > 0) {
            DB.insertAll(addLists);
        }
        if (updateList.size() > 0) {
            DB.updateAll(updateList);
        }
        if (deleteList.size() > 0) {
            DB.deleteAll(deleteList);
        }
    }



    public List<SelectOption> readDict(String code) {
        SystemDict record = new QSystemDict().code.eq(code).setMaxRows(1).findOne();
        Assert.notNull(record, "数据字典不存在");
        return record.getItems();
    }


    /**
     * 根据字典代码批量加载数据字典
     *
     * @param dictCodeList dict代码列表
     * @return {@code List<SelectOptionMap>}
     */
    public List<SelectOptionMap> batchReadDict(List<String> dictCodeList) {
        ArrayList<SelectOptionMap> res = new ArrayList<>();
        new QSystemDict().code.in( dictCodeList ).findEach( x -> {
            SelectOptionMap selectOptionMap = new SelectOptionMap().setKeyword( x.getCode() ).setItems( x.getItems() );
            res.add( selectOptionMap );
        } );
        return res;

    }
}
